package com.sinszm.mdb.pagebar;

import com.sinszm.common.exception.ApiException;
import com.sinszm.mdb.pagebar.annotation.Th;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Web端列表排序响应对象
 *
 * <p>
 * 仅仅用于对PageHelper的二次组装
 * </p>
 *
 * @author chenjianbo
 */
@ApiModel(value = "分页结果")
public class WebPageResponse<T extends WebIndex> implements Serializable {

    private static final long serialVersionUID = -8678880584701513990L;

    /**
     * 表头信息
     */
    @ApiModelProperty(value = "表头信息", dataType = "List")
    private List<Header> headers = new ArrayList<>();

    /**
     * 总页数
     */
    @ApiModelProperty(value = "总页数", dataType = "Integer")
    private int pages;

    /**
     * 总记录数
     */
    @ApiModelProperty(value = "总记录数", dataType = "Long")
    protected long total;

    /**
     * 当前页
     */
    @ApiModelProperty(value = "当前页", dataType = "Integer")
    private int pageNum;

    /**
     * 每页的数量
     */
    @ApiModelProperty(value = "每页数量", dataType = "Integer")
    private int pageSize;

    /**
     * 结果集
     */
    @ApiModelProperty(value = "结果", dataType = "List")
    protected List<T> list;

    /**
     * 前一页
     */
    @ApiModelProperty(value = "前一页", dataType = "Integer")
    private int prePage;

    /**
     * 下一页
     */
    @ApiModelProperty(value = "下一页", dataType = "Integer")
    private int nextPage;

    /**
     * 扩展数据
     */
    @ApiModelProperty(value = "扩展数据", dataType = "Map")
    private Map<String, Object> extData = new ConcurrentHashMap<>(0);

    public WebPageResponse(Class<T> tClass) {
        if (tClass == null) {
            throw new ApiException("PAGE-RESPONSE-ERR-001","Class不能为空");
        }
        Map<String, Field> fieldMap = new HashMap<>(0);
        if (tClass.getFields().length != 0) {
            for (Field field : tClass.getFields()) {
                fieldMap.put(field.getName(), field);
            }
        }
        for (Field field : tClass.getDeclaredFields()) {
            if (!fieldMap.containsKey(field.getName())) {
                fieldMap.put(field.getName(), field);
            }
        }
        fieldMap = getSuperClassFields(fieldMap, tClass);
        Field[] fields = fieldMap.values().toArray(new Field[0]);
        if (fields.length > 0) {
            for (Field field : fields) {
                Th th = field.getAnnotation(Th.class);
                if (th == null) {
                    continue;
                }
                headers.add(new Header(
                        th.sorted()? (StringUtils.isEmpty(th.dbName())? field.getName() : th.dbName()) : field.getName(),
                        field.getName(),
                        th.value(),
                        th.fixed(),
                        th.sorted(),
                        th.index()
                ));
            }
            Collections.sort(headers);
        }
    }

    /**
     * 获取所有父类的字段
     * @param map   映射
     * @param clazz 类
     * @return  x
     */
    private Map<String, Field> getSuperClassFields(Map<String, Field> map, Class<?> clazz) {
        Class<?> superClazz = clazz.getSuperclass();
        if (superClazz.equals(Object.class)) {
            return map;
        }
        Field[] fields = superClazz.getDeclaredFields();
        for (Field field : fields) {
            if (!map.containsKey(field.getName())) {
                map.put(field.getName(), field);
            }
        }
        return getSuperClassFields(map, superClazz);
    }

    @ApiModel(value = "表头信息")
    private static class Header implements Comparable<Header> {
        @ApiModelProperty(value = "字段名", dataType = "String")
        private String field;
        @ApiModelProperty(value = "数据字段名", dataType = "String")
        private String dataField;
        @ApiModelProperty(value = "列名", dataType = "String")
        private String fieldName;
        @ApiModelProperty(value = "是否固定列", dataType = "Boolean")
        private boolean fixed;
        @ApiModelProperty(value = "是否可以动态排序", dataType = "Boolean")
        private boolean sorted;
        @ApiModelProperty(value = "排序号", dataType = "Integer")
        private int index;

        public Header(String field, String dataField, String fieldName, boolean fixed, boolean sorted, int index) {
            this.field = field;
            this.dataField = dataField;
            this.fieldName = fieldName;
            this.fixed = fixed;
            this.sorted = sorted;
            this.index = index;
        }

        @Override
        public int compareTo(Header o) {
            return this.index - o.index;
        }

        public String getField() {
            return field;
        }

        public void setField(String field) {
            this.field = field;
        }

        public String getFieldName() {
            return fieldName;
        }

        public void setFieldName(String fieldName) {
            this.fieldName = fieldName;
        }

        public boolean isFixed() {
            return fixed;
        }

        public void setFixed(boolean fixed) {
            this.fixed = fixed;
        }

        public boolean isSorted() {
            return sorted;
        }

        public void setSorted(boolean sorted) {
            this.sorted = sorted;
        }

        public String getDataField() {
            return dataField;
        }

        public void setDataField(String dataField) {
            this.dataField = dataField;
        }

        public int getIndex() {
            return index;
        }

        public void setIndex(int index) {
            this.index = index;
        }
    }

    public List<Header> getHeaders() {
        return headers;
    }

    public void setHeaders(List<Header> headers) {
        this.headers = headers;
    }

    public int getPages() {
        return pages;
    }

    public void setPages(int pages) {
        this.pages = pages;
    }

    public long getTotal() {
        return total;
    }

    public void setTotal(long total) {
        this.total = total;
    }

    public int getPageNum() {
        return pageNum;
    }

    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public List<T> getList() {
        return list;
    }

    public void setList(List<T> list) {
        this.list = list;
    }

    public int getPrePage() {
        return prePage;
    }

    public void setPrePage(int prePage) {
        this.prePage = prePage;
    }

    public int getNextPage() {
        return nextPage;
    }

    public void setNextPage(int nextPage) {
        this.nextPage = nextPage;
    }

    @Override
    public String toString() {
        return Json.toJson(this, JsonFormat.nice());
    }

    public static class Bill<T> {
        /**
         * 表头信息
         */
        private List<Header> headers;

        /**
         * 结果集
         */
        private List<T> list;

        public Bill(List<Header> headers, List<T> list) {
            this.headers = headers;
            this.list = list;
        }

        public List<Header> getHeaders() {
            return headers;
        }

        public void setHeaders(List<Header> headers) {
            this.headers = headers;
        }

        public List<T> getList() {
            return list;
        }

        public void setList(List<T> list) {
            this.list = list;
        }
    }

    public Map<String, Object> getExtData() {
        return extData;
    }

    public void setExtData(Map<String, Object> extData) {
        this.extData = extData;
    }
}